package matrix;

import java.util.ArrayList;

public abstract class SSLE {

	protected Matrix x, a, b;
	protected long time;
	protected ArrayList<String> steps;

	public SSLE solve(Matrix a, Matrix b, boolean buildSteps) throws Exception {
		this.a = a;
		this.b = b;
		if (!(this instanceof Iterative))
			x = new Matrix(1, a.height(), a.type());
		steps = new ArrayList<String>() {
			private static final long serialVersionUID = -2074051616910861141L;

			@Override
			public String toString() {
				String out = "\\begin{array}{}";
				for (String s : this)
					out += s + "\\\\\n";
				out += "\\end{array}";
				return out;
			}
		};
		if (buildSteps) {
			steps.add("AX = B");
			steps.add(a.toLatex() + "X=" + b.toLatex());
			steps.add("Solve \\;\\; for \\;\\; X?");
		}
		time = System.nanoTime();
		solve(buildSteps);
		time = System.nanoTime() - time;
		return this;
	}

	protected abstract void solve(boolean buildSteps) throws Exception;

	public int type() {
		return a.type();
	}

	public ArrayList<String> steps() {
		return steps;
	}

	public abstract String nSteps();

	public long time() {
		return time;
	}

	public Matrix err() {
		return a.multiply(x).subtract(b);
	}

	public double absErr() {
		Matrix err = err();
		double maxErr = 0;
		for (int i = 0; i < err.height(); i++)
			for (int j = 0; j < err.width(); j++)
				maxErr = Math.max(maxErr, Math.abs(err.get(j, i).doubleValue()));
		return maxErr;
	}

	public Matrix soln() {
		return x;
	}
}
